import { _decorator, Component, SpriteFrame, resources, Sprite } from 'cc';
import { ZombieAction, CommonData, ZombieNames } from '../Utils/CommonData';
import { EventBus, TYPE } from '../Utils/EventBus';
import { is2DArray } from '../Utils/Utils';
const { ccclass, property } = _decorator;

export type ZombieName = 'normal';

const mapTable: Record<string, ZombieNames> = {
  normalZombie: 'normal',
};

@ccclass('ZombieBase')
export class ZombieBase extends Component {
  @property
  public speed: number = 0;

  @property
  public maxHp: number = 0;

  @property()
  public frameRate: number = 0.1;

  public hp: number = 0;
  public isEating: boolean = false;
  public targetPlant: Node | null = null;
  public sprite: Sprite | Sprite[] = null;
  public _currentAction: ZombieAction = 'idle';
  public _frameIndex: number = 0;
  public _timer: number = 0;
  public isLoad: boolean = false;

  public async init() {
    this.hp = this.maxHp;
    this.isLoad = true;
  }

  getAloneSprite() {
    const aloneSprite = this.node.getChildByName('alone');
    const spriteNode = aloneSprite.getChildByName('sprite');
    aloneSprite.active = true;
    this.node.getChildByName('split').active = false;
    this.sprite = spriteNode.getComponent(Sprite);
  }

  getSplitSprite() {
    const splitSprite = this.node.getChildByName('split');
    splitSprite.active = true;
    this.node.getChildByName('alone').active = false;
    const head = splitSprite.getChildByName('head');
    const body = splitSprite.getChildByName('body');
    head.active = true;
    body.active = true;
    this.sprite = [head.getComponent(Sprite), body.getComponent(Sprite)];
  }

  moveForward(dt: number) {
    this.isEating = false;
    if (
      (this._currentAction === 'run' && this.speed) ||
      (this._currentAction === 'dying' && this.speed)
    ) {
      const pos = this.node.position;
      this.updateAnimation(dt);
      this.node.setPosition(pos.x - this.speed * dt, pos.y, pos.z);
    }
    if (this._currentAction === 'die') {
      this.updateAnimation(dt);
    }
  }

  attack(dt: number) {
    this.isEating = true;
    this.updateAnimation(dt);
  }

  updateAnimation(dt: number) {
    const frames = CommonData.instance.zombieFramesMap
      .get(mapTable[this.node.name])
      .get(this._currentAction);
    if (!frames || !frames.length) return;
    this._timer += dt;
    if (this._timer >= this.frameRate) {
      this._timer = 0;
      this._frameIndex++;
      if (
        is2DArray(frames) &&
        this._frameIndex >= (frames as SpriteFrame[][]).map(arr=>arr.length).reduce((a,b)=>Math.max(a,b))
      ) {
        this._frameIndex = 0;
      } else {
        if (!is2DArray(frames) && this._frameIndex >= frames.length) {
          if (this._currentAction === 'die') {
            this.node.destroy();
            EventBus.emit(TYPE.ZOMBIE_DEATH);
            return;
          } else {
            this._frameIndex = 0;
          }
        }
      }
      if (this.sprite) {
        if (is2DArray(frames)) {
          (this.sprite as Sprite[]).forEach((sprite, index) => {
            let f = (frames as SpriteFrame[][])[index];
            console.log(this._frameIndex);
            if (f.length >= this._frameIndex) {
              sprite.spriteFrame = f[this._frameIndex];
            } else {
              this.node.getChildByName('split').getChildByName('head').active =
                false;
            }
          });
        } else {
          (this.sprite as Sprite).spriteFrame = (frames as SpriteFrame[])[
            this._frameIndex
          ];
        }
      }
    }
  }

  playAction(action: ZombieAction) {
    if (this._currentAction === action) return;
    this._currentAction = action;
    this._frameIndex = 0;
    this._timer = 0;
    const frames = CommonData.instance.zombieFramesMap
      .get(mapTable[this.node.name])
      .get(this._currentAction);
    if (frames && frames.length) {
      if (is2DArray(frames)) {
        this.getSplitSprite();
        (this.sprite as Sprite[]).forEach((sprite, index) => {
          sprite.spriteFrame = (frames as SpriteFrame[][])[index][0];
        });
      } else {
        this.getAloneSprite();
        (this.sprite as Sprite).spriteFrame = (frames as SpriteFrame[])[0];
      }
    }
  }
}
